Skip to content

.NET: Foundry.Hosting IT - avoid MSB3026 in publish step#5689

Merged
rogerbarreto merged 3 commits intomainfrom
features/foundry-hosting-it-msb3026-fix
May 7, 2026
Merged

.NET: Foundry.Hosting IT - avoid MSB3026 in publish step#5689
rogerbarreto merged 3 commits intomainfrom
features/foundry-hosting-it-msb3026-fix

Conversation

@rogerbarreto
Copy link
Copy Markdown
Member

@rogerbarreto rogerbarreto commented May 7, 2026

Problem

CI run https://github.com/microsoft/agent-framework/actions/runs/25446865848/job/74653338378 failed in the dotnet-foundry-hosted-it job with:

error MSB3026: Could not copy "obj/Release/net10.0/Microsoft.Agents.AI.Abstractions.dll"
to "bin/Release/net10.0/Microsoft.Agents.AI.Abstractions.dll".
The process cannot access the file ... because it is being used by another process.

Root cause

Job run two MSBuild back to back on same tree:

  1. Build Foundry hosted IT (and its deps) fill dotnet/src/<lib>/bin/Release/net10.0/*.dll. Helper process (VBCSCompiler) keep file handle open.
  2. it-build-image.ps1 run dotnet publish for linux-musl-x64. Publish rebuild same lib DLL into same path. First build still hold handle. Boom: MSB3026.

Fix

In it-build-image.ps1 add explicit opt-in switch -UsePrebuiltProjectReferences. CI pass switch -> publish skip ProjectReference rebuild, eat prebuilt DLL in place. No file lock fight, no extra rebuild.

Local default = no switch = publish rebuild as normal. If user have stale obj/Release/net10.0 from old build, preflight throw clear error: tell user to pass switch OR delete old obj. No silent stale image.

CI keep prebuild step. Test --no-build need it too.

Bonus: fix flaky UT

Same PR run hit flaky test AgentFrameworkResponseHandlerTelemetryTests.CreateAsync_AlreadyInstrumentedAgent_EmitsSingleSpanPerRunAsync:

System.InvalidOperationException : Collection was modified; enumeration operation may not execute.

Test use plain List<Activity> for OTel AddInMemoryExporter. Exporter write from background Activity stop callback. Parallel test on same global ActivitySource feed every listener. Add race with assertion enumerate. Boom.

Fix: tiny ConcurrentActivityList : ICollection<Activity> wrapper. Lock add/enumerate. Test call Snapshot() for assertion (lock + copy). All 4 telemetry test use it.

Verification

Local repro on Windows, three path:

Path Setup Switch Result
A clean checkout none publish + docker build OK
B prebuild done -UsePrebuiltProjectReferences skip rebuild, Abstractions.dll ticks unchanged before/after
C prebuild done none preflight throw with recovery instructions

Telemetry UT: 30 isolated runs + 5 full assembly runs (216 test each), 0 fail.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Addresses intermittent dotnet publish failures (MSB3026 file-in-use) in the Foundry.Hosting integration-test container build by avoiding a second rebuild of referenced libraries when they were already built by the job’s prebuild step.

Changes:

  • Updated it-build-image.ps1 to detect prebuilt library outputs and conditionally add -p:BuildProjectReferences=false to dotnet publish.
  • Added workflow documentation explaining why the prebuild step exists and why publish is configured to avoid rebuilding project references.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
dotnet/tests/Foundry.Hosting.IntegrationTests/scripts/it-build-image.ps1 Adds conditional logic to skip ProjectReference rebuild during publish when prebuilt outputs exist.
.github/workflows/dotnet-build-and-test.yml Documents the CI rationale for the publish behavior to prevent MSB3026 collisions.

Comment thread dotnet/tests/Foundry.Hosting.IntegrationTests/scripts/it-build-image.ps1 Outdated
@rogerbarreto rogerbarreto force-pushed the features/foundry-hosting-it-msb3026-fix branch from 247b632 to 0bf21e4 Compare May 7, 2026 09:43
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Automated Code Review

Reviewers: 4 | Confidence: 93% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Design Approach


Automated review by rogerbarreto's agents

…flake

CI publish step: gate the BuildProjectReferences=false fast-path on an explicit -UsePrebuiltProjectReferences switch (passed by the workflow) instead of marker detection. Adds a preflight error when stale obj/Release/net10.0 outputs would cause CS0579, with actionable recovery instructions.

Telemetry UT flake: AgentFrameworkResponseHandlerTelemetryTests was using a plain List<Activity> for OTel's InMemoryExporter. The exporter writes from background Activity completion callbacks while parallel tests on the same global ActivitySource feed every listener, racing against the assertion's enumeration and throwing 'Collection was modified'. Replaced with a small thread-safe ConcurrentActivityList that locks add/enumerate and returns a snapshot for assertions.
@rogerbarreto rogerbarreto added this pull request to the merge queue May 7, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 7, 2026
@rogerbarreto rogerbarreto added this pull request to the merge queue May 7, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

5 participants